package com.zzb.weixin.listener;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import com.zzb.weixin.WeiXinMsgFactory;
import com.zzb.weixin.constant.WXUrlName;
import com.zzb.weixin.model.msg.basic.Msg;

/**
 * 抽象会话 此会话声明周期在一个请求响应内。 通过继承类实现各种消息的处理方法
 * 
 * @author marker
 * */
public abstract class ListenerManager {

	// 输入流
	private InputStream is;
	// 输出流
	private OutputStream os;

	/** Document构建类 */
	private static DocumentBuilder builder;
	private static TransformerFactory tffactory;

	static {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		try {
			builder = factory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		// 格式化工厂对象
		tffactory = TransformerFactory.newInstance();
	}

	/**
	 * ListenerManager
	 * 
	 */
	public ListenerManager() {
	}

	/**
	 * 解析微信消息，并传递给对应方法,仅能供未加密消息使用
	 * @param is
	 * @param os
	 * @return
	 * @throws Exception
	 */
	public Msg process(InputStream is, OutputStream os) throws Exception {
		Msg msg = null;
		this.os = os;
		try {
			Document document = builder.parse(is);
			msg = WeiXinMsgFactory.getMsg(document);
			onMsg(msg);
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return msg;
	}
	/**
	 * 解析微信消息，并传递给对应方法
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public Msg process(HttpServletRequest request,HttpServletResponse response) throws Exception {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		InputStream is  = request.getInputStream();
		OutputStream os = response.getOutputStream();
		
		String timestamp = (String) request.getAttribute(WXUrlName.TIME_STAMP);
		String nonce = (String) request.getAttribute(WXUrlName.NONCE);
		String msgSignature = (String) request.getAttribute(WXUrlName.MSG_SIGNATURE);
		String encryptType = (String) request.getAttribute(WXUrlName.ENCRYPT_TYPE);
		Msg msg = null;
		this.os = os;
		try {
			//如果需要aes解密,先解密,再调用正常消息处理函数
			if("aes".equals(encryptType)){
				
			}
			Document document = builder.parse(is);
			msg = WeiXinMsgFactory.getMsg(document);
			onMsg(msg);
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return msg;
	}

	/**
	 * 回传消息给微信服务器 只能再接收到微信服务器消息后，才能调用此方法
	 * 
	 * @param msg
	 *            消息对象（支持：文本、音乐、图文）
	 * */
	public void callback(Msg msg) {
		Document document = builder.newDocument();
		msg.setDocument(document);
		Element el = msg.write();
		document.appendChild(el);
		try {
			Transformer transformer = tffactory.newTransformer();
			transformer.transform(new DOMSource(document), new StreamResult(
					new OutputStreamWriter(os, "utf-8")));
		} catch (Exception e) {
			e.printStackTrace();// 保存dom至目输出流
		} finally {
			close();
		}
	}
	public void callback() {
		try {
			os.write("".getBytes());
		} catch (Exception e) {
			e.printStackTrace();// 保存dom至目输出流
		} finally {
			close();
		}
	}

	/**
	 * 关闭
	 * */
	public void close() {
		try {
			if (is != null) {
				is.close();
			}
			if (os != null) {
				os.flush();
				os.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 错误消息
	 * 
	 * @param msg
	 */
	public abstract void onMsg(int errorCode);
	
	public abstract void onMsg(Msg msg);
}
